/**
 * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved.
 */

#ifndef PANDA_ECMASCRIPT_INTERPRETER_INL_H
#define PANDA_ECMASCRIPT_INTERPRETER_INL_H

#include "macros.h"
#include "plugins/ecmascript/runtime/ecma_string.h"
#include "plugins/ecmascript/runtime/interpreter/ecma-interpreter.h"
#include "plugins/ecmascript/runtime/interpreter/js_frame-inl.h"
#include "plugins/ecmascript/runtime/interpreter/slow_runtime_stub.h"
#include "plugins/ecmascript/runtime/interpreter/js_decode_call_instr.h"
#include "plugins/ecmascript/runtime/interpreter/fast_runtime_stub-inl.h"
#include "plugins/ecmascript/runtime/ecma_vm.h"
#include "plugins/ecmascript/runtime/intrinsics-inl.h"
#include "plugins/ecmascript/runtime/js_generator_object.h"
#include "plugins/ecmascript/runtime/js_array.h"
#include "plugins/ecmascript/runtime/ecma_profiling.h"
#include "plugins/ecmascript/runtime/handle_storage_check.h"
#include "plugins/ecmascript/compiler/ecmascript_extensions/thread_environment_api.h"
#include "runtime/interpreter/interpreter-inl.h"
#include "runtime/interpreter/instruction_handler_base.h"

namespace ark::ecmascript {

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INTRINSIC_CALL_SETACC(intrinsic_call)                \
    {                                                        \
        JSTaggedValue result(intrinsic_call);                \
        ASSERT(!this->GetJSThread()->HasPendingException()); \
        SetAccFromTaggedValue(result);                       \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INTRINSIC_CALL_CHECK(intrinsic_call)                 \
    {                                                        \
        JSTaggedValue result(intrinsic_call);                \
        if (UNLIKELY(result.IsException())) {                \
            this->MoveToExceptionHandler();                  \
            return;                                          \
        }                                                    \
        ASSERT(!this->GetJSThread()->HasPendingException()); \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INTRINSIC_CALL_CHECK_SETACC(intrinsic_call)          \
    {                                                        \
        JSTaggedValue result(intrinsic_call);                \
        if (UNLIKELY(result.IsException())) {                \
            this->MoveToExceptionHandler();                  \
            return;                                          \
        }                                                    \
        ASSERT(!this->GetJSThread()->HasPendingException()); \
        SetAccFromTaggedValue(result);                       \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INTRINSIC_CALL_CHECK_SETACC_SETENV(intrinsic_call)   \
    {                                                        \
        JSTaggedValue result(intrinsic_call);                \
        if (UNLIKELY(result.IsException())) {                \
            this->MoveToExceptionHandler();                  \
            return;                                          \
        }                                                    \
        ASSERT(!this->GetJSThread()->HasPendingException()); \
        SetLexicalEnv(result);                               \
        SetAccFromTaggedValue(result);                       \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INTERPRETER_RETURN_IF_ABRUPT(result)                 \
    do {                                                     \
        if (result.IsException()) {                          \
            this->MoveToExceptionHandler();                  \
            return;                                          \
        }                                                    \
        ASSERT(!this->GetJSThread()->HasPendingException()); \
    } while (false)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define UPDATE_UNARY_ARITH_PROFILE(lhs) \
    if constexpr (IS_PROFILE_ENABLED) { \
        UpdateUnaryArithProfile(lhs);   \
    } else {                            \
        UNUSED_VAR(lhs);                \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define UPDATE_BINARY_ARITH_PROFILE(lhs, rhs) \
    if constexpr (IS_PROFILE_ENABLED) {       \
        UpdateBinaryArithProfile(lhs, rhs);   \
    } else {                                  \
        UNUSED_VAR(lhs);                      \
        UNUSED_VAR(rhs);                      \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define UPDATE_MOD_PROFILE(lhs, rhs)              \
    if constexpr (IS_PROFILE_ENABLED) {           \
        UpdateBinaryArithProfile<true>(lhs, rhs); \
    } else {                                      \
        UNUSED_VAR(lhs);                          \
        UNUSED_VAR(rhs);                          \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define UPDATE_TYPE_OF_PROFILE(lhs)     \
    if constexpr (IS_PROFILE_ENABLED) { \
        UpdateTypeOfProfile(lhs);       \
    } else {                            \
        UNUSED_VAR(lhs);                \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define UPDATE_CALL_PROFILE(func)       \
    if constexpr (IS_PROFILE_ENABLED) { \
        UpdateCallProfile(func);        \
    } else {                            \
        UNUSED_VAR(func);               \
    }

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define GET_PROFILE_ADDRESS(addr)       \
    if constexpr (IS_PROFILE_ENABLED) { \
        addr = GetProfileAddress();     \
    } else {                            \
        addr = nullptr;                 \
    }

template <BytecodeInstruction::Opcode OPCODE, bool IS_QUICKENED>
class JSFrameHelper {
public:
    template <BytecodeInstruction::Format FORMAT, class InstructionHandler>
    ALWAYS_INLINE static uint32_t GetNumberActualArgsDyn([[maybe_unused]] InstructionHandler *instrHandler)
    {
        return JSGetNumberActualArgsDyn<FORMAT, OPCODE, IS_QUICKENED>(instrHandler->GetInst());
    }

    template <BytecodeInstruction::Format FORMAT, class InstructionHandler>
    ALWAYS_INLINE static void CopyArgumentsDyn(InstructionHandler *instrHandler, Frame *newFrame, uint32_t numVregs,
                                               uint32_t numActualArgs)
    {
        Frame *prevFrame = instrHandler->GetFrame();
        BytecodeInstruction prevInst = instrHandler->GetInst();
        auto *thread = JSThread::Cast(instrHandler->GetThread());

        uint64_t prevRawFuncObj = JSGetCalleDyn<FORMAT, OPCODE, IS_QUICKENED>(prevFrame, prevInst);

        JSCopyArgumets<FORMAT, OPCODE, IS_QUICKENED>(thread, prevFrame, prevRawFuncObj, prevInst, newFrame, numVregs,
                                                     numActualArgs);
    }

    template <class RuntimeIfaceT>
    ALWAYS_INLINE static Frame *CreateFrame(ManagedThread *thread, uint32_t nregsSize, Method *method, Frame *prev,
                                            uint32_t nregs, uint32_t numActualArgs)
    {
        return ::ark::CreateFrame<JSEnv>(thread->GetStackFrameAllocator(), nregsSize, method, prev, nregs,
                                         numActualArgs);
    }
};

template <class RuntimeIfaceT, bool IS_DYNAMIC, bool IS_DEBUG, bool IS_PROFILE_ENABLED = false,
          bool IS_QUICKENED = false>
class InstructionHandler : public interpreter::InstructionHandler<RuntimeIfaceT, IS_DYNAMIC, IS_DEBUG> {
public:
    ALWAYS_INLINE inline explicit InstructionHandler(interpreter::InstructionHandlerState *state)
        : interpreter::InstructionHandler<RuntimeIfaceT, IS_DYNAMIC, IS_DEBUG>(state)
    {
    }

    ALWAYS_INLINE JSThread *GetJSThread() const
    {
        return JSThread::Cast(interpreter::InstructionHandler<RuntimeIfaceT, IS_DYNAMIC, IS_DEBUG>::GetThread());
    }

    ALWAYS_INLINE JSTaggedValue GetRegAsTaggedValue(uint16_t v)
    {
        return VRegAsTaggedValue(this->GetFrame()->GetVReg(v));
    }

    ALWAYS_INLINE JSTaggedType GetRegAsTaggedType(uint16_t v)
    {
        return VRegAsTaggedType(this->GetFrame()->GetVReg(v));
    }

    ALWAYS_INLINE JSTaggedValue GetAccAsTaggedValue()
    {
        return VRegAsTaggedValue(this->GetAcc());
    }

    JSTaggedType *GetStkArgs(uint16_t firstArgIdx)
    {
        static_assert(sizeof(interpreter::VRegister) == sizeof(JSTaggedType));
        auto thread = JSThread::Cast(this->GetThread());
        return reinterpret_cast<JSTaggedType *>(&thread->GetCurrentFrame()->GetVReg(firstArgIdx));
    }

    JSTaggedValue GetCurrentFunction()
    {
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto numVregs = this->GetFrame()->GetMethod()->GetNumVregs();
        return GetRegAsTaggedValue(numVregs + js_method_args::FUNC_IDX);
    }

    JSTaggedValue GetCurrentNewTarget()
    {
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto numVregs = this->GetFrame()->GetMethod()->GetNumVregs();
        return GetRegAsTaggedValue(numVregs + js_method_args::NEW_TARGET_IDX);
    }

    JSTaggedValue GetCurrentThis()
    {
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto numVregs = this->GetFrame()->GetMethod()->GetNumVregs();
        return GetRegAsTaggedValue(numVregs + js_method_args::THIS_IDX);
    }

    JSTaggedValue GetGlobalObject()
    {
        auto thread = JSThread::Cast(this->GetThread());
        return thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject();
    }

    ark::ecmascript::JSHandle<ark::ecmascript::GlobalEnv> GetGlobalEnv()
    {
        auto thread = JSThread::Cast(this->GetThread());
        return thread->GetEcmaVM()->GetGlobalEnv();
    }

    ObjectFactory *GetFactory()
    {
        auto thread = JSThread::Cast(this->GetThread());
        return thread->GetEcmaVM()->GetFactory();
    }

    ALWAYS_INLINE void SetAccFromTaggedValue(JSTaggedValue v)
    {
        this->GetAcc().Set(v.GetRawData());
    }

    ALWAYS_INLINE void SaveAccToFrame()
    {
        this->GetFrame()->SetAcc(this->GetAcc());
    }

    ALWAYS_INLINE void RestoreAccFromFrame()
    {
        this->GetAcc() = this->GetFrame()->GetAcc();
    }

    JSHandle<JSTaggedValue> GetMethodName(JSHandle<ECMAObject> callTarget)
    {
        auto thread = JSThread::Cast(this->GetThread());
        JSHandle<JSFunction> thisFunc = JSHandle<JSFunction>::Cast(callTarget);
        return JSFunctionBase::GetFunctionName(thread, JSHandle<JSFunctionBase>(thisFunc));
    }

    ALWAYS_INLINE EcmascriptEnvironment *GetCurrentEnv()
    {
        return JSFrame::GetJSEnv(this->GetFrame());
    }

    ALWAYS_INLINE uint64_t GetThisFuncRawValue()
    {
        return JSTaggedValue(GetCurrentEnv()->GetThisFunc()).GetRawData();
    }

    ALWAYS_INLINE ConstantPool *GetConstantPool()
    {
        return ConstantPool::Cast(GetCurrentEnv()->GetConstantPool());
    }

    ALWAYS_INLINE uint64_t GetConstantPoolRawValue()
    {
        return JSTaggedValue(GetCurrentEnv()->GetConstantPool()).GetRawData();
    }

    ALWAYS_INLINE uint64_t LoadFromConstantPool(BytecodeId id)
    {
        return GetConstantPool()->GetObjectFromCache(id.AsIndex()).GetRawData();
    }

    ALWAYS_INLINE LexicalEnv *GetLexicalEnv()
    {
        return LexicalEnv::Cast(GetCurrentEnv()->GetLexicalEnv());
    }

    ALWAYS_INLINE uint64_t GetLexicalEnvRawValue()
    {
        return JSTaggedValue(GetCurrentEnv()->GetLexicalEnv()).GetRawData();
    }

    ALWAYS_INLINE void SetLexicalEnv(JSTaggedValue lexEnv)
    {
        return GetCurrentEnv()->SetLexicalEnv(lexEnv.GetTaggedObject());
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaReturnDyn()
    {
        LOG_INST() << "ecma.return.dyn";

        auto frame = this->GetFrame();

        if (UNLIKELY(frame->IsInitobj())) {
            auto accIn = GetAccAsTaggedValue();
            JSFunction *func = JSFunction::Cast(GetCurrentFunction().GetTaggedObject());
            if (LIKELY(accIn.IsECMAObject())) {
                // preserve current value
            } else if (LIKELY(func->IsBase() || accIn.IsUndefined())) {
                SetAccFromTaggedValue(GetCurrentThis());
            } else {
                [[maybe_unused]] EcmaHandleScope handleScope(this->GetJSThread());
                ASSERT(func->IsDerivedConstructor());
                JSHandle<JSObject> error = GetFactory()->GetJSError(
                    ErrorType::TYPE_ERROR, "Derived constructor must return object or undefined");
                this->GetJSThread()->SetException(error.GetTaggedValue());
                this->MoveToExceptionHandler();
                return;
            }
        }
        this->GetFrame()->SetAcc((this->GetAcc()));
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaReturnundefined()
    {
        LOG_INST() << "return.undefined";

        auto frame = this->GetFrame();

        if (UNLIKELY(frame->IsInitobj())) {
            auto accIn = GetAccAsTaggedValue();
            JSFunction *func = JSFunction::Cast(GetCurrentFunction().GetTaggedObject());
            if (LIKELY(func->IsBase() || accIn.IsUndefined())) {
                SetAccFromTaggedValue(GetCurrentThis());
            } else {
                [[maybe_unused]] EcmaHandleScope handleScope(this->GetJSThread());
                ASSERT(func->IsDerivedConstructor());
                JSHandle<JSObject> error = GetFactory()->GetJSError(
                    ErrorType::TYPE_ERROR, "Derived constructor must return object or undefined");
                this->GetJSThread()->SetException(error.GetTaggedValue());
                this->MoveToExceptionHandler();
                return;
            }
        } else {
            SetAccFromTaggedValue(JSTaggedValue::Undefined());
        }
        this->GetFrame()->SetAcc((this->GetAcc()));
    }

    // Redefine method from base class
    ALWAYS_INLINE void HandleReturnStackless()
    {
        interpreter::InstructionHandler<RuntimeIfaceT, IS_DYNAMIC, IS_DEBUG>::HandleReturnStackless();
    }

    template <BytecodeInstruction::Format FORMAT, BytecodeInstruction::Opcode OPCODE>
    ALWAYS_INLINE void DoEcmaCallDyn()
    {
        this->UpdateBytecodeOffset();
        this->SaveAccToFrame();

        JSThread *jsThread = this->GetJSThread();
        [[maybe_unused]] HandleStorageCheck handleStorageCheck(jsThread);
        uint64_t function = JSGetCalleDyn<FORMAT, OPCODE, IS_QUICKENED>(jsThread->GetCurrentFrame(), this->GetInst());

        if (UNLIKELY(!JSTaggedValue(function).IsCallable())) {
            [[maybe_unused]] EcmaHandleScope handleScope(jsThread);
            JSHandle<JSObject> error = GetFactory()->GetJSError(ErrorType::TYPE_ERROR, "is not callable");
            jsThread->SetException(error.GetTaggedValue());
            this->MoveToExceptionHandler();
            return;
        }

        ECMAObject *thisFunc = ECMAObject::Cast(JSTaggedValue(function).GetHeapObject());
        Method *method = thisFunc->GetCallTarget();
        if (method->IsNative()) {
            // Native
            ASSERT(method->GetNumVregs() == 0);
            UPDATE_CALL_PROFILE(thisFunc);

            uint32_t numActualArgs = JSGetNumberActualArgsDyn<FORMAT, OPCODE, IS_QUICKENED>(this->GetInst());
            uint32_t numArgs = std::max(method->GetNumArgs(), numActualArgs);

            Frame *prevFrame = this->GetFrame();
            BytecodeInstruction prevInst = this->GetInst();
            Frame *frame =
                JSFrame::CreateNativeFrame(jsThread, method, jsThread->GetCurrentFrame(), numArgs, numActualArgs);

            JSCopyArgumets<FORMAT, OPCODE, IS_QUICKENED>(this->GetJSThread(), prevFrame, function, prevInst, frame, 0,
                                                         numActualArgs);

            // Call native method
            jsThread->SetCurrentFrame(frame);
            JSTaggedValue retValue = JSFrame::ExecuteNativeMethod(jsThread, frame, method, numActualArgs);
            ASSERT(jsThread->GetCurrentFrame() == frame);
            jsThread->SetCurrentFrameIsCompiled(false);
            jsThread->SetCurrentFrame(prevFrame);

            JSFrame::DestroyNativeFrame(jsThread, frame);
            if (UNLIKELY(jsThread->HasPendingException())) {
                this->MoveToExceptionHandler();
                return;
            }
            ASSERT(JSTaggedValue(retValue).IsException() == false);
            SetAccFromTaggedValue(retValue);
            this->template MoveToNextInst<FORMAT, true>();
            return;
        }

        JSFunction *jsFunction = JSFunction::Cast(thisFunc);
        if (UNLIKELY(jsFunction->IsClassConstructor())) {
            [[maybe_unused]] EcmaHandleScope handleScope(jsThread);
            JSHandle<JSObject> error =
                GetFactory()->GetJSError(ErrorType::TYPE_ERROR, "class constructor cannot be called without 'new'");
            jsThread->SetException(error.GetTaggedValue());
            this->MoveToExceptionHandler();
            return;
        }

        UPDATE_CALL_PROFILE(thisFunc);
        if (method->HasCompiledCode()) {  // AOT, JIT
            this->template CallCompiledCode<FORMAT, true>(method);
        } else {  // Interpreter
            [[maybe_unused]] EcmaHandleScope scope(jsThread);
            JSHandle<JSFunction> functionHandle(jsThread, jsFunction);

            method->DecrementHotnessCounter<true>(0, nullptr, false, JSTaggedValue(function));
            if (UNLIKELY(jsThread->HasPendingException())) {
                return;
            }

            // Call stackless interpreter
            this->template CallInterpreterStackless<JSFrameHelper<OPCODE, IS_QUICKENED>, FORMAT,
                                                    /* is_dynamic = */ true,
                                                    /* is_range= */ false, /* accept_acc= */ false,
                                                    /* initobj= */ false, /* call= */ true>(method);
            if (UNLIKELY(jsThread->HasPendingException())) {
                return;
            }

            ConstantPool *constantPool = ConstantPool::Cast(functionHandle->GetConstantPool().GetHeapObject());
            JSTaggedValue lexicalEnv = functionHandle->GetLexicalEnv();

            // Init EcmascriptEnvironment
            EcmascriptEnvironment *newEnv = JSFrame::GetJSEnv(this->GetFrame());
            new (newEnv) EcmascriptEnvironment(constantPool, lexicalEnv.GetHeapObject(), *functionHandle);
        }
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaNewobjdynrange()
    {
        auto constexpr OPCODE = BytecodeInstruction::Opcode::ECMA_NEWOBJDYNRANGE_PREF_IMM16_V8_PROF16;

        auto firstArgRegIdx = this->GetInst().template GetVReg<FORMAT, 0>();
        auto numRangeArgs = this->GetInst().template GetImm<FORMAT, 0>();

        LOG_INST() << "newobjDynrange " << numRangeArgs << " v" << firstArgRegIdx;

        this->UpdateBytecodeOffset();
        // acc: out, thus dead

        auto rangeArgs = GetStkArgs(firstArgRegIdx);
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto ctorHandle = JSHandle<JSTaggedValue>(ToUintPtr(&rangeArgs[0]));
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto newTargetHandle = JSHandle<JSTaggedValue>(ToUintPtr(&rangeArgs[1]));

        auto ctor = ctorHandle.GetTaggedValue();
        auto newTarget = newTargetHandle.GetTaggedValue();

        auto thread = this->GetJSThread();

        if (LIKELY(ctor.IsJSFunction() && ctor.IsConstructor())) {
            auto ctorFunc = JSFunction::Cast(ctor.GetTaggedObject());
            auto method = ctorFunc->GetMethod();

            UPDATE_CALL_PROFILE(ctorFunc);

            if (LIKELY(!method->IsNative() && (ctorFunc->IsBase() || ctorFunc->IsDerivedConstructor()))) {
                JSTaggedValue thisObj;
                if (ctorFunc->IsBase()) {
                    [[maybe_unused]] EcmaHandleScope handleScope(thread);
                    thisObj = GetFactory()
                                  ->NewJSObjectByConstructor(JSHandle<JSFunction>(ctorHandle), newTargetHandle)
                                  .GetTaggedValue();
                    INTERPRETER_RETURN_IF_ABRUPT(thisObj);
                    // gc may fire
                    ctor = ctorHandle.GetTaggedValue();
                    ctorFunc = JSFunction::Cast(ctor.GetTaggedObject());
                    newTarget = newTargetHandle.GetTaggedValue();
                } else {
                    thisObj = JSTaggedValue::Undefined();
                }
                SetAccFromTaggedValue(thisObj);

                if (UNLIKELY(method->HasCompiledCode())) {
                    [[maybe_unused]] EcmaHandleScope handleScope(thread);
                    JSHandle<JSTaggedValue> thisHandle(thread, thisObj);

                    // 'this' object to be set from acc in i2c
                    this->template CallCompiledCode<FORMAT, true>(method);

                    auto accIn = GetAccAsTaggedValue();
                    // gc may fire
                    ctor = ctorHandle.GetTaggedValue();
                    ctorFunc = JSFunction::Cast(ctor.GetTaggedObject());
                    if (LIKELY(accIn.IsECMAObject())) {
                        // preserve current value
                    } else if (LIKELY(ctorFunc->IsBase() || accIn.IsUndefined())) {
                        SetAccFromTaggedValue(thisHandle.GetTaggedValue());
                    } else {
                        ASSERT(ctorFunc->IsDerivedConstructor());
                        JSHandle<JSObject> error = GetFactory()->GetJSError(
                            ErrorType::TYPE_ERROR, "Derived constructor must return object or undefined");
                        this->GetJSThread()->SetException(error.GetTaggedValue());
                        this->MoveToExceptionHandler();
                        return;
                    }
                } else {
                    method->DecrementHotnessCounter<true>(0, nullptr, false, ctor);
                    if (UNLIKELY(thread->HasPendingException())) {
                        return;
                    }

                    // Call stackless interpreter
                    this->template CallInterpreterStackless<JSFrameHelper<OPCODE, IS_QUICKENED>, FORMAT,
                                                            /* is_dynamic = */ true,
                                                            /* is_range= */ false, /* accept_acc= */ false,
                                                            /* initobj= */ true, /* call= */ true>(method);
                    if (UNLIKELY(thread->HasPendingException())) {
                        return;
                    }
                    this->GetFrame()
                        ->GetVReg(method->GetNumVregs() + js_method_args::THIS_IDX)
                        .SetValue(thisObj.GetRawData());

                    // Init EcmascriptEnvironment
                    auto ctorFuncHandle = JSHandle<JSFunction>(ctorHandle);
                    ConstantPool *constantPool = ConstantPool::Cast(ctorFuncHandle->GetConstantPool().GetHeapObject());
                    JSTaggedValue lexicalEnv = ctorFuncHandle->GetLexicalEnv();
                    EcmascriptEnvironment *newEnv = JSFrame::GetJSEnv(this->GetFrame());
                    new (newEnv) EcmascriptEnvironment(constantPool, lexicalEnv.GetHeapObject(), *ctorFuncHandle);
                }

                return;
            }

            if (LIKELY(ctorFunc->IsBuiltinConstructor())) {
                ASSERT(method->IsNative() && method->GetNumVregs() == 0);

                uint32_t numActualArgs = JSGetNumberActualArgsDyn<FORMAT, OPCODE, IS_QUICKENED>(this->GetInst());
                uint32_t numArgs = std::max(method->GetNumArgs(), numActualArgs);

                Frame *prevFrame = this->GetFrame();
                BytecodeInstruction prevInst = this->GetInst();
                Frame *frame =
                    JSFrame::CreateNativeFrame(thread, method, thread->GetCurrentFrame(), numArgs, numActualArgs);

                JSTaggedValue retValue;
                if (UNLIKELY(frame == nullptr)) {
                    retValue = JSTaggedValue::Exception();
                } else {
                    JSCopyArgumets<FORMAT, OPCODE, IS_QUICKENED>(this->GetJSThread(), prevFrame, ctor.GetRawData(),
                                                                 prevInst, frame, 0, numActualArgs);
                    frame->GetVReg(0 + js_method_args::THIS_IDX).SetValue(JSTaggedValue::VALUE_UNDEFINED);

                    // Call native method
                    thread->SetCurrentFrame(frame);
                    retValue = JSFrame::ExecuteNativeMethod(thread, frame, method, numActualArgs);

                    ASSERT(thread->GetCurrentFrame() == frame);
                    thread->SetCurrentFrameIsCompiled(false);
                    thread->SetCurrentFrame(prevFrame);
                    JSFrame::DestroyNativeFrame(thread, frame);
                }

                if (UNLIKELY(thread->HasPendingException())) {
                    this->MoveToExceptionHandler();
                    return;
                }
                ASSERT(JSTaggedValue(retValue).IsException() == false);
                SetAccFromTaggedValue(retValue);
                this->template MoveToNextInst<FORMAT, true>();
                return;
            }
        }

        // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::NewobjDynrange(thread, numRangeArgs - 2U, ctor.GetRawData(),
                                                               newTarget.GetRawData(), rangeArgs + 2U));
        // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall0dyn()
    {
        LOG_INST() << "call0.dyn";

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL0DYN_PREF_NONE_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall1dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();

        LOG_INST() << "call1.dyn "
                   << "v" << v0;

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL1DYN_PREF_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "call2.dyn "
                   << "v" << v0 << ", v" << v1;

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL2DYN_PREF_V8_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall3dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        auto v2 = this->GetInst().template GetVReg<FORMAT, 2>();
        LOG_INST() << "call3.dyn "
                   << "v" << v0 << ", v" << v1 << ", v" << v2;

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL3DYN_PREF_V8_V8_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall0thisdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();

        LOG_INST() << "callthis0.dyn "
                   << "this v:" << v0;

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL0THISDYN_PREF_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall1thisdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "callthis1.dyn "
                   << "this v" << v0 << ", v" << v1;

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL1THISDYN_PREF_V8_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall2thisdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        auto v2 = this->GetInst().template GetVReg<FORMAT, 2>();
        LOG_INST() << "callthis2.dyn "
                   << "this v" << v0 << ", v" << v1 << ", v" << v2;

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL2THISDYN_PREF_V8_V8_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCall3thisdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        auto v2 = this->GetInst().template GetVReg<FORMAT, 2>();
        auto v3 = this->GetInst().template GetVReg<FORMAT, 3>();
        LOG_INST() << "callthis3.dyn "
                   << "this v" << v0 << ", v" << v1 << ", v" << v2 << ", v" << v3;

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALL3THISDYN_PREF_V8_V8_V8_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCallirangedyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto numArgs = this->GetInst().template GetImm<FORMAT, 0>();

        auto func = GetRegAsTaggedValue(v0);

        LOG_INST() << "calli.rangedyn " << numArgs + 3 << ", v" << v0 << " , func:" << func.GetRawData();

        this->template DoEcmaCallDyn<FORMAT, BytecodeInstruction::Opcode::ECMA_CALLIRANGEDYN_PREF_IMM16_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCallithisrangedyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto numArgs = this->GetInst().template GetImm<FORMAT, 0>();

        LOG_INST() << "calli.dyn.this.range " << numArgs + 2 << ", v" << v0;

        this->template DoEcmaCallDyn<FORMAT,
                                     BytecodeInstruction::Opcode::ECMA_CALLITHISRANGEDYN_PREF_IMM16_V8_PROF16>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCallspreaddyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        auto v2 = this->GetInst().template GetVReg<FORMAT, 2>();

        LOG_INST() << "callspreaddyn"
                   << " v" << v0 << " v" << v1 << " v" << v2;

        uint64_t func = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t array = GetRegAsTaggedValue(v2).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::CallspreadDyn(this->GetJSThread(), func, obj, array));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaJfalse()
    {
        auto imm = this->GetInst().template GetImm<FORMAT>();
        LOG_INST() << "jfalse" << imm;

        auto acc = GetAccAsTaggedValue();

        if (acc == TaggedValue::False()) {
            this->template UpdateBranchStatistics<true>();
            if (!this->InstrumentBranches(imm)) {
                this->template JumpToInst<false>(imm);
            }
        } else {
            this->template UpdateBranchStatistics<false>();
            this->template MoveToNextInst<FORMAT, false>();
        }
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaJtrue()
    {
        auto imm = this->GetInst().template GetImm<FORMAT>();
        LOG_INST() << "jtrue" << imm;

        auto acc = GetAccAsTaggedValue();

        if (acc == TaggedValue::True()) {
            this->template UpdateBranchStatistics<true>();
            if (!this->InstrumentBranches(imm)) {
                this->template JumpToInst<false>(imm);
            }
        } else {
            this->template UpdateBranchStatistics<false>();
            this->template MoveToNextInst<FORMAT, false>();
        }
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdinfinity()
    {
        LOG_INST() << "ldinfinity";

        INTRINSIC_CALL_SETACC(intrinsics::Ldinfinity());

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdglobalthis()
    {
        LOG_INST() << "ldglobalthis";
        INTRINSIC_CALL_SETACC(intrinsics::Ldglobalthis(this->GetJSThread()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdundefined()
    {
        LOG_INST() << "ldundefined";
        INTRINSIC_CALL_SETACC(intrinsics::Ldundefined());
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdnull()
    {
        LOG_INST() << "ldnull";
        INTRINSIC_CALL_SETACC(intrinsics::Ldnull());
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdsymbol()
    {
        LOG_INST() << "ldsymbol";
        INTRINSIC_CALL_SETACC(intrinsics::Ldsymbol(this->GetJSThread()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdglobal()
    {
        LOG_INST() << "ldglobal";
        INTRINSIC_CALL_SETACC(intrinsics::Ldglobal(this->GetJSThread()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdtrue()
    {
        LOG_INST() << "ldtrue";
        INTRINSIC_CALL_SETACC(intrinsics::Ldtrue());
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdfalse()
    {
        LOG_INST() << "ldfalse";
        INTRINSIC_CALL_SETACC(intrinsics::Ldfalse());
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdbigint()
    {
        auto bigInt = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "ld.bigint " << bigInt << "n";

        auto thread = this->GetJSThread();
        INTRINSIC_CALL_SETACC(intrinsics::Ldbigint(thread, LoadFromConstantPool(bigInt)));
        this->template MoveToNextInst<FORMAT, false>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdlexenvdyn()
    {
        LOG_INST() << "ldlexenvDyn ";
        SetAccFromTaggedValue(JSTaggedValue(GetLexicalEnvRawValue()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGetunmappedargs()
    {
        LOG_INST() << "getunmappedargs";

        uint32_t actualNumArgs =
            this->GetFrame()->GetNumActualArgs() - js_method_args::NUM_MANDATORY_ARGS;  // not compile-time
        uint32_t startIdx = this->GetFrame()->GetMethod()->GetNumVregs() + js_method_args::NUM_MANDATORY_ARGS;

        auto thread = JSThread::Cast(this->GetThread());
        JSTaggedValue res = SlowRuntimeStub::GetUnmappedArgs(thread, actualNumArgs, GetStkArgs(startIdx));

        INTERPRETER_RETURN_IF_ABRUPT(res);
        SetAccFromTaggedValue(res);
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAsyncfunctionenter()
    {
        LOG_INST() << "asyncfunctionenter";
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::AsyncFunctionEnter(this->GetJSThread()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdboolean()
    {
        // it38 Unimplement
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdnumber()
    {
        // it38 Unimplement
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdstring()
    {
        // it38 Unimplement
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaTonumber()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::tonumber"
                   << " v" << v0;
        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();

        UPDATE_UNARY_ARITH_PROFILE(value);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Tonumber(this->GetJSThread(), value));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaNegdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "negdyn"
                   << " v" << v0;

        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();

        UPDATE_UNARY_ARITH_PROFILE(value);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::NegDyn(this->GetJSThread(), value));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaNotdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "notdyn"
                   << " v" << v0;

        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();

        UPDATE_UNARY_ARITH_PROFILE(value);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::NotDyn(this->GetJSThread(), value));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaIncdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "incdyn"
                   << " v" << v0;

        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();

        UPDATE_UNARY_ARITH_PROFILE(value);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::IncDyn(this->GetJSThread(), value));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDecdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "decdyn"
                   << " v" << v0;

        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();

        UPDATE_UNARY_ARITH_PROFILE(value);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::DecDyn(this->GetJSThread(), value));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaRethrowdyn()
    {
        LOG_INST() << "rethrowdyn";
        auto thread = JSThread::Cast(this->GetThread());
        auto acc = GetAccAsTaggedValue();

        if (acc.IsHole()) {
            this->template MoveToNextInst<FORMAT, true>();
            return;
        }

        SlowRuntimeStub::ThrowDyn(thread, acc);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowdyn()
    {
        LOG_INST() << "throwdyn";
        auto thread = JSThread::Cast(this->GetThread());
        auto acc = GetAccAsTaggedValue();
        SlowRuntimeStub::ThrowDyn(thread, acc);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaTypeofdyn()
    {
        LOG_INST() << "typeofdyn";
        uint64_t acc = GetAccAsTaggedValue().GetRawData();

        UPDATE_TYPE_OF_PROFILE(acc);
        INTRINSIC_CALL_SETACC(intrinsics::TypeofDyn(this->GetJSThread(), acc));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaToboolean()
    {
        LOG_INST() << "toboolean";

        UPDATE_UNARY_ARITH_PROFILE(GetAccAsTaggedValue().GetRawData());

        INTRINSIC_CALL_SETACC(intrinsics::Toboolean(GetAccAsTaggedValue().GetRawData()));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaNegate()
    {
        LOG_INST() << "negate";
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        UPDATE_UNARY_ARITH_PROFILE(value);

        INTRINSIC_CALL_SETACC(intrinsics::Negate(value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaIsundefined()
    {
        LOG_INST() << "isundefined";
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_SETACC(intrinsics::IsUndefined(value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaIstrue()
    {
        LOG_INST() << "istrue";
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_SETACC(intrinsics::IsTrue(value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaIsfalse()
    {
        LOG_INST() << "isfalse";
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_SETACC(intrinsics::IsFalse(value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaIscoercible()
    {
        LOG_INST() << "iscoercible";
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_SETACC(intrinsics::IsCoercible(value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGetpropiterator()
    {
        LOG_INST() << "getpropiterator";

        uint64_t acc = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GetPropIterator(this->GetJSThread(), acc));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaResumegenerator()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "resumegenerator"
                   << " v" << v0;

        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_SETACC(intrinsics::ResumeGenerator(value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGetresumemode()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "getresumemode"
                   << " v" << v0;

        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_SETACC(intrinsics::GetResumeMode(value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGetiterator()
    {
        LOG_INST() << "getiterator";

        uint64_t obj = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GetIterator(this->GetJSThread(), obj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGetasynciterator()
    {
        LOG_INST() << "getasynciterator";

        uint64_t obj = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GetAsyncIterator(this->GetJSThread(), obj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowundefined()
    {
        // the instrunction has beed retired
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowconstassignment()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto prop = JSTaggedValue(LoadFromConstantPool(stringId));
        LOG_INST() << "throwconstassignment "
                   << "string_id:" << ConvertToPandaString(EcmaString::Cast(prop.GetHeapObject()));

        auto thread = JSThread::Cast(this->GetThread());
        SlowRuntimeStub::ThrowConstAssignment(thread, prop);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowthrownotexists()
    {
        LOG_INST() << "throwthrownotexists";
        auto thread = JSThread::Cast(this->GetThread());
        SlowRuntimeStub::ThrowThrowNotExists(thread);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowpatternnoncoercible()
    {
        LOG_INST() << "throwpatternnoncoercible";
        auto thread = JSThread::Cast(this->GetThread());
        SlowRuntimeStub::ThrowPatternNonCoercible(thread);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowifnotobject()
    {
        LOG_INST() << "throwifnotobject";

        if (GetAccAsTaggedValue().IsECMAObject()) {
            this->template MoveToNextInst<FORMAT, true>();
            return;
        }
        auto thread = JSThread::Cast(this->GetThread());
        SlowRuntimeStub::ThrowIfNotObject(thread);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCloseiterator()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "closeiterator"
                   << " v" << v0;

        uint64_t iter = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t acc = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::CloseIterator(this->GetJSThread(), iter, acc));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdobject()
    {
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdfunction()
    {
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAdd2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::add2dyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Add2Dyn(this->GetJSThread(), left, right));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSub2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::sub2dyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Sub2Dyn(this->GetJSThread(), left, right));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaMul2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::mul2dyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Mul2Dyn(this->GetJSThread(), left, right));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDiv2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::div2dyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Div2Dyn(this->GetJSThread(), left, right));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaMod2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::mod2dyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_MOD_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Mod2Dyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaEqdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::eqdyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::EqDyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaNoteqdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "noteqdyn"
                   << " v" << v0;

        uint64_t lhs = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t rhs = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(lhs, rhs);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::NotEqDyn(this->GetJSThread(), lhs, rhs));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLessdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::lessdyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::LessDyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLesseqdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::lesseqdyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::LessEqDyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGreaterdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::greaterdyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GreaterDyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGreatereqdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::greatereqdyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GreaterEqDyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaShl2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "shl2dyn"
                   << " v" << v0;

        uint64_t lhs = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t rhs = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(lhs, rhs);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Shl2Dyn(this->GetJSThread(), lhs, rhs));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaShr2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "shr2dyn"
                   << " v" << v0;

        uint64_t lhs = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t rhs = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(lhs, rhs);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Shr2Dyn(this->GetJSThread(), lhs, rhs));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAshr2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "ashr2dyn"
                   << " v" << v0;

        uint64_t lhs = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t rhs = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Ashr2Dyn(this->GetJSThread(), lhs, rhs));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAnd2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "and2dyn"
                   << " v" << v0;

        uint64_t lhs = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t rhs = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(lhs, rhs);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::And2Dyn(this->GetJSThread(), lhs, rhs));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaOr2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "or2dyn"
                   << " v" << v0;

        uint64_t lhs = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t rhs = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(lhs, rhs);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Or2Dyn(this->GetJSThread(), lhs, rhs));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaXor2dyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "xor2dyn"
                   << " v" << v0;

        uint64_t lhs = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t rhs = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(lhs, rhs);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Xor2Dyn(this->GetJSThread(), lhs, rhs));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDelobjprop()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "delobjprop"
                   << " v0" << v0 << " v1" << v1;

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t prop = GetRegAsTaggedValue(v1).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::Delobjprop(this->GetJSThread(), obj, prop));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefineglobalvar()
    {
        // it38 Unimplement
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefinelocalvar()
    {
        // it38 Unimplement
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefinefuncexpr()
    {
        // it38 Unimplement
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefinefuncdyn()
    {
        auto methodId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "definefuncDyn"
                   << " v" << v0 << std::hex << methodId;

        uint64_t env = GetRegAsTaggedValue(v0).GetRawData();
        auto cp = GetConstantPool();
        uint64_t method = cp->GetObjectFromCache(methodId.AsIndex()).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::DefinefuncDyn(this->GetJSThread(), method, env, JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefinencfuncdyn()
    {
        auto methodId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "definencfuncDyn"
                   << " v" << v0 << ", method_id: " << std::hex << methodId;

        uint64_t env = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t homeObject = GetAccAsTaggedValue().GetRawData();

        auto cp = GetConstantPool();
        uint64_t method = cp->GetObjectFromCache(methodId.AsIndex()).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::DefineNCFuncDyn(this->GetJSThread(), method, env, homeObject, JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefinemethod()
    {
        auto methodId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "definemethod"
                   << " v" << v0 << std::hex << methodId;

        uint64_t taggedCurEnv = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t homeObject = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        auto cp = GetConstantPool();
        uint64_t method = cp->GetObjectFromCache(methodId.AsIndex()).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::DefineMethod(this->GetJSThread(), method, taggedCurEnv, homeObject,
                                                             JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaRefeqdyn()
    {
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaExpdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::expdyn"
                   << " v" << v0;
        uint64_t base = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t exponent = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::ExpDyn(this->GetJSThread(), base, exponent));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCallruntimerange()
    {
        // it38 Unimplement
        LOG_INST() << "-------------";
        UNREACHABLE();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaIsindyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "isindyn"
                   << " v" << v0;

        uint64_t prop = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::IsinDyn(this->GetJSThread(), prop, obj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaInstanceofdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "instanceofdyn"
                   << " v" << v0;

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t target = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::InstanceofDyn(this->GetJSThread(), obj, target));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStrictnoteqdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "strictnoteq"
                   << " v" << v0;

        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_SETACC(intrinsics::StrictNotEqDyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStricteqdyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsics::stricteqdyn"
                   << " v" << v0;
        uint64_t left = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t right = GetAccAsTaggedValue().GetRawData();

        UPDATE_BINARY_ARITH_PROFILE(left, right);

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::StrictEqDyn(this->GetJSThread(), left, right));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdlexvardyn()
    {
        auto level = this->GetInst().template GetImm<FORMAT, 0>();
        auto slot = this->GetInst().template GetImm<FORMAT, 1>();
        LOG_INST() << "ldlexvardyn"
                   << " level:" << level << " slot:" << slot;
        auto lexEnv = GetLexicalEnvRawValue();
        INTRINSIC_CALL_SETACC(intrinsics::LdLexVarDyn(this->GetJSThread(), level, slot, lexEnv));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdlexdyn()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto prop = LoadFromConstantPool(stringId);
        auto level = this->GetInst().template GetImm<FORMAT, 0>();
        auto slot = this->GetInst().template GetImm<FORMAT, 1>();
        LOG_INST() << "ldlexdyn"
                   << " string_id:" << ConvertToPandaString(EcmaString::Cast(JSTaggedValue(prop).GetHeapObject()))
                   << " level:" << level << " slot:" << slot;

        auto lexEnv = GetLexicalEnvRawValue();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::LdLexDyn(this->GetJSThread(), prop, level, slot, lexEnv));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStlexvardyn()
    {
        auto level = this->GetInst().template GetImm<FORMAT, 0>();
        auto slot = this->GetInst().template GetImm<FORMAT, 1>();

        LOG_INST() << "stlexvardyn"
                   << " level:" << level << " slot:" << slot;

        uint64_t value = GetAccAsTaggedValue().GetRawData();
        uint64_t lexEnv = GetLexicalEnvRawValue();
        intrinsics::StLexVarDyn(this->GetJSThread(), level, slot, value, lexEnv);

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStlexdyn()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto prop = LoadFromConstantPool(stringId);
        auto level = this->GetInst().template GetImm<FORMAT, 0>();
        auto slot = this->GetInst().template GetImm<FORMAT, 1>();
        LOG_INST() << "stlexdyn"
                   << " string_id:" << ConvertToPandaString(EcmaString::Cast(JSTaggedValue(prop).GetHeapObject()))
                   << " level:" << level << " slot:" << slot;

        uint64_t value = GetAccAsTaggedValue().GetRawData();
        uint64_t lexEnv = GetLexicalEnvRawValue();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::StLexDyn(this->GetJSThread(), prop, level, slot, value, lexEnv));

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaNewlexenvdyn()
    {
        auto numVars = this->GetInst().template GetImm<FORMAT, 0>();

        LOG_INST() << "newlexenvdyn"
                   << " imm " << numVars;

        auto lexEnv = GetLexicalEnvRawValue();
        INTRINSIC_CALL_CHECK_SETACC_SETENV(intrinsics::NewlexenvDyn(this->GetJSThread(), numVars, lexEnv));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCopylexenvdyn()
    {
        LOG_INST() << "copylexenvdyn";

        auto lexEnv = GetLexicalEnvRawValue();
        INTRINSIC_CALL_CHECK_SETACC_SETENV(intrinsics::CopylexenvDyn(lexEnv));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateiterresultobj()
    {
        auto done = this->GetInst().template GetImm<FORMAT, 0>();
        LOG_INST() << "createiterresultobj"
                   << " done " << std::boolalpha << done;

        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateIterResultObj(this->GetJSThread(), value, done));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSuspendgenerator()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "suspendgenerator"
                   << " v" << v0;

        auto genObj = GetRegAsTaggedValue(v0);
        auto value = GetAccAsTaggedValue();
        // SuspendGenerator preserves BCOffset and acc
        this->GetFrame()->SetBytecodeOffset(this->GetBytecodeOffset());
        SaveAccToFrame();

        auto thread = JSThread::Cast(this->GetThread());
        auto res = SlowRuntimeStub::SuspendGenerator(thread, genObj, value);

        LOG(DEBUG, INTERPRETER) << "Exit: SuspendGenerator: res - " << res.GetRawData();

        INTERPRETER_RETURN_IF_ABRUPT(res);
        SetAccFromTaggedValue(res);
        SaveAccToFrame();
        // return to caller frame
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSuspendasyncgenerator()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "suspendasyncgenerator"
                   << " v" << v0;

        auto genObj = GetRegAsTaggedValue(v0);
        auto value = GetAccAsTaggedValue();
        // SuspendAsyncGenerator preserves BCOffset and acc
        this->GetFrame()->SetBytecodeOffset(this->GetBytecodeOffset());
        SaveAccToFrame();

        auto thread = JSThread::Cast(this->GetThread());
        auto res = SlowRuntimeStub::SuspendAsyncGenerator(thread, genObj, value);

        LOG(DEBUG, INTERPRETER) << "Exit: SuspendAsyncGenerator: res - " << res.GetRawData();

        INTERPRETER_RETURN_IF_ABRUPT(res);
        SetAccFromTaggedValue(res);
        SaveAccToFrame();
        ASSERT(!this->GetFrame()->IsStackless());
        // return to caller frame
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAsyncfunctionawait()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();

        LOG_INST() << "asyncfunctionawait"
                   << " v" << v0;

        uint64_t asyncFuncObj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::AsyncFunctionAwait(this->GetJSThread(), asyncFuncObj, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAsyncfunctionresolve()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "asyncfunctionresolve"
                   << " v" << v0;

        uint64_t asyncFuncObj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::AsyncFunctionResolve(this->GetJSThread(), asyncFuncObj, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAsyncfunctionreject()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "asyncfunctionreject"
                   << " v" << v0;

        uint64_t asyncFuncObj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::AsyncFunctionReject(this->GetJSThread(), asyncFuncObj, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAsyncgeneratorresolve()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "asyncgeneratorresolve"
                   << " v" << v0;

        uint64_t asyncFuncObj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::AsyncGeneratorResolve(this->GetJSThread(), asyncFuncObj, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaAsyncgeneratorreject()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "asyncgeneratorreject"
                   << " v" << v0;

        uint64_t asyncFuncObj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::AsyncGeneratorReject(this->GetJSThread(), asyncFuncObj, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaNewobjspreaddyn()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "intrinsic::newobjspearddyn"
                   << " v" << v0 << " v" << v1;

        uint64_t func = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t newTarget = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t array = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::NewobjspreadDyn(this->GetJSThread(), func, newTarget, array));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowtdz()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto prop = JSTaggedValue(LoadFromConstantPool(stringId));
        LOG_INST() << "intrinsic::throwundefinedifhole "
                   << "string_id:" << ConvertToPandaString(EcmaString::Cast(prop.GetHeapObject()));

        auto thread = JSThread::Cast(this->GetThread());
        SlowRuntimeStub::ThrowTdz(thread, prop);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStownbyname()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto id = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "stownbyname "
                   << "v" << v0 << " string_id:" << id.AsIndex();

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        INTRINSIC_CALL_CHECK(intrinsics::StOwnByName(this->GetJSThread(), LoadFromConstantPool(id), obj, value));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateemptyarray()
    {
        LOG_INST() << "createemptyarray";

        INTRINSIC_CALL_SETACC(intrinsics::CreateEmptyArray(this->GetJSThread()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateemptyobject()
    {
        LOG_INST() << "createemptyobject";

        INTRINSIC_CALL_SETACC(intrinsics::CreateEmptyObject(this->GetJSThread()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateobjectwithbuffer()
    {
        auto literalarrayId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "createobjectwithbuffer"
                   << " literalArrayId:" << literalarrayId.AsIndex();

        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::CreateObjectWithBuffer(this->GetJSThread(), LoadFromConstantPool(literalarrayId)));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreatearraywithbuffer()
    {
        auto literalarrayId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "createarraywithbuffer"
                   << " literalArrayId:" << literalarrayId.AsIndex();

        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::CreateArrayWithBuffer(this->GetJSThread(), LoadFromConstantPool(literalarrayId)));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateregexpwithliteral()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto flags = this->GetInst().template GetImm<FORMAT, 0>();
        LOG_INST() << "createregexpwithliteral"
                   << " string_id: " << stringId << " flags:" << flags;

        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::CreateRegExpWithLiteral(this->GetJSThread(), LoadFromConstantPool(stringId), flags));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaImportmodule()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "importmodule "
                   << "string_id:" << std::hex << stringId.AsIndex();

        INTRINSIC_CALL_SETACC(intrinsics::ImportModule(this->GetJSThread(), LoadFromConstantPool(stringId)));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStmodulevar()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "stmodulevar "
                   << "string_id:" << stringId;

        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        intrinsics::StModuleVar(this->GetJSThread(), LoadFromConstantPool(stringId), value);
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCopymodule()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "copymodule "
                   << " v" << v0;

        uint64_t srcModule = GetRegAsTaggedValue(v0).GetRawData();
        SaveAccToFrame();
        intrinsics::CopyModule(this->GetJSThread(), srcModule);
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdmodvarbyname()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto stringId = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "ldmodvarbyname "
                   << "string_id:" << stringId.AsIndex();

        uint64_t moduleObj = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_SETACC(
            intrinsics::LdModvarByName(this->GetJSThread(), LoadFromConstantPool(stringId), moduleObj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGetmethod()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto stringId = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "getmethod v" << v0 << " string_id:" << stringId;
        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GetMethod(this->GetJSThread(), LoadFromConstantPool(stringId), obj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGettemplateobject()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsic::gettemplateobject"
                   << " v" << v0;

        uint64_t literal = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GetTemplateObject(this->GetJSThread(), literal));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaGetnextpropname()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsic::getnextpropname"
                   << " v" << v0;

        uint64_t iter = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::GetNextPropName(this->GetJSThread(), iter));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCopydataproperties()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "intrinsic::copydataproperties"
                   << " v" << v0 << " v" << v1;

        uint64_t dst = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t src = GetRegAsTaggedValue(v1).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::CopyDataProperties(this->GetJSThread(), dst, src));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStownbyindex()
    {
        uint32_t idx = this->GetInst().template GetImm<FORMAT, 0>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "stownbyindex"
                   << " v" << v0 << " imm" << idx;

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        INTRINSIC_CALL_CHECK(intrinsics::StOwnByIndex(this->GetJSThread(), idx, obj, value));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStownbyvalue()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "stownbyvalue"
                   << " v" << v0 << " v" << v1;

        uint64_t receiver = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t propKey = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        INTRINSIC_CALL_CHECK(intrinsics::StOwnByValue(this->GetJSThread(), receiver, propKey, value));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateobjectwithexcludedkeys()
    {
        auto numKeys = this->GetInst().template GetImm<FORMAT, 0>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        uint16_t firstArgRegIdx = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "createobjectwithexcludedkeys " << numKeys << " v" << v0 << std::hex << firstArgRegIdx;

        auto obj = GetRegAsTaggedValue(v0);
        auto thread = JSThread::Cast(this->GetThread());

        auto res = SlowRuntimeStub::CreateObjectWithExcludedKeys(thread, numKeys, obj, GetStkArgs(firstArgRegIdx));
        INTERPRETER_RETURN_IF_ABRUPT(res);
        SetAccFromTaggedValue(res);

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefinegeneratorfunc()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto methodId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "define generator function"
                   << " v" << v0;

        uint64_t env = GetRegAsTaggedValue(v0).GetRawData();
        auto cp = GetConstantPool();
        uint64_t method = cp->GetObjectFromCache(methodId.AsIndex()).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::DefineGeneratorFunc(this->GetJSThread(), method, env, JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefineasyncfunc()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto methodId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "define async function"
                   << " v" << v0;

        uint64_t env = GetRegAsTaggedValue(v0).GetRawData();
        auto cp = GetConstantPool();
        uint64_t method = cp->GetObjectFromCache(methodId.AsIndex()).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::DefineAsyncFunc(this->GetJSThread(), method, env, JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefineasyncgeneratorfunc()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto methodId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "define async generator function"
                   << " v" << v0;

        uint64_t env = GetRegAsTaggedValue(v0).GetRawData();
        auto cp = GetConstantPool();
        uint64_t method = cp->GetObjectFromCache(methodId.AsIndex()).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::DefineAsyncGeneratorFunc(this->GetJSThread(), method, env, JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdhole()
    {
        LOG_INST() << "intrinsic::ldhole";
        INTRINSIC_CALL_SETACC(intrinsics::Ldhole());

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCopyrestargs()
    {
        auto restIdx = this->GetInst().template GetImm<FORMAT, 0>();
        LOG_INST() << "copyrestargs"
                   << " index: " << restIdx;

        auto *state = this->GetFrame();
        uint32_t numVregs = state->GetMethod()->GetNumVregs();
        // Exclude func, new_target and "this"
        int32_t actualNumArgs = state->GetNumActualArgs() - js_method_args::NUM_MANDATORY_ARGS;
        int32_t tmp = actualNumArgs - restIdx;
        uint32_t restNumArgs = (tmp > 0) ? tmp : 0;
        uint32_t startIdx = numVregs + js_method_args::NUM_MANDATORY_ARGS + restIdx;

        auto thread = JSThread::Cast(this->GetThread());
        JSTaggedValue res = SlowRuntimeStub::CopyRestArgs(thread, restNumArgs, GetStkArgs(startIdx));
        INTERPRETER_RETURN_IF_ABRUPT(res);
        SetAccFromTaggedValue(res);
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefinegettersetterbyvalue()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        auto v2 = this->GetInst().template GetVReg<FORMAT, 2>();
        auto v3 = this->GetInst().template GetVReg<FORMAT, 3>();
        LOG_INST() << "definegettersetterbyvalue"
                   << " v" << v0 << " v" << v1 << " v" << v2 << " v" << v3;

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t prop = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t getter = GetRegAsTaggedValue(v2).GetRawData();
        uint64_t setter = GetRegAsTaggedValue(v3).GetRawData();
        uint64_t flag = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::DefineGetterSetterByValue(this->GetJSThread(), obj, prop, getter, setter, flag));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdobjbyindex()
    {
        uint32_t idx = this->GetInst().template GetImm<FORMAT, 0>();
        LOG_INST() << "ldobjbyindex"
                   << " imm" << idx;

        uint64_t obj = GetAccAsTaggedValue().GetRawData();
        void *profAddress;
        GET_PROFILE_ADDRESS(profAddress);
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::LdObjByIndex(this->GetJSThread(), idx, obj, profAddress));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStobjbyindex()
    {
        uint32_t idx = this->GetInst().template GetImm<FORMAT, 0>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "stobjbyindex"
                   << " v" << v0 << " imm" << idx;

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();
        void *profAddress;
        GET_PROFILE_ADDRESS(profAddress);
        SaveAccToFrame();
        INTRINSIC_CALL_CHECK(intrinsics::StObjByIndex(this->GetJSThread(), idx, obj, value, profAddress));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdobjbyvalue()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "Ldobjbyvalue"
                   << " v" << v0;

        uint64_t receiver = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t propKey = GetAccAsTaggedValue().GetRawData();
        uint64_t func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::LdObjByValue(this->GetJSThread(), receiver, propKey, this->GetBytecodeOffset(), func));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStobjbyvalue()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "stobjbyvalue"
                   << " v" << v0 << " v" << v1;

        uint64_t receiver = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t propKey = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK(
            intrinsics::StObjByValue(this->GetJSThread(), receiver, propKey, value, this->GetBytecodeOffset(), func));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdsuperbyvalue()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "Ldsuperbyvalue"
                   << " v" << v0;

        uint64_t receiver = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t propKey = GetAccAsTaggedValue().GetRawData();
        uint64_t func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::LdSuperByValue(this->GetJSThread(), receiver, propKey, func));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStsuperbyvalue()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "stsuperbyvalue"
                   << " v" << v0 << " v" << v1;

        uint64_t receiver = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t propKey = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();
        uint64_t func = GetThisFuncRawValue();

        SaveAccToFrame();
        INTRINSIC_CALL_CHECK(intrinsics::StSuperByValue(this->GetJSThread(), receiver, propKey, value, func));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaTryldglobalbyname()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::TryLdGlobalByName(this->GetJSThread(), LoadFromConstantPool(stringId),
                                                                  this->GetBytecodeOffset(), func));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaTrystglobalbyname()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "trystglobalbyname"
                   << " string_id:" << stringId;

        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK(intrinsics::TryStGlobalByName(this->GetJSThread(), LoadFromConstantPool(stringId), value,
                                                           this->GetBytecodeOffset(), func));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdglobalvar()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "ldglobalvar "
                   << " string_id:" << stringId;

        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::LdGlobalVar(this->GetJSThread(), LoadFromConstantPool(stringId),
                                                            this->GetBytecodeOffset(), func));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdobjbyname()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "ldobjbyname"
                   << " string_id:" << stringId;
        uint64_t obj = GetAccAsTaggedValue().GetRawData();

        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::LdObjByName(this->GetJSThread(), LoadFromConstantPool(stringId), obj,
                                                            this->GetBytecodeOffset(), func));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStobjbyname()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto stringId = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "stobjbyname "
                   << "v" << v0 << " string_id:" << stringId.AsIndex();

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK(intrinsics::StObjByName(this->GetJSThread(), LoadFromConstantPool(stringId), obj, value,
                                                     this->GetBytecodeOffset(), func));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdsuperbyname()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "ldsuperbyname"
                   << " string_id:" << stringId.AsIndex();

        uint64_t obj = GetAccAsTaggedValue().GetRawData();
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::LdSuperByName(this->GetJSThread(), LoadFromConstantPool(stringId), obj, func));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStsuperbyname()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();

        LOG_INST() << "stsuperbyname"
                   << "v" << v0 << " string_id:" << stringId.AsIndex();

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK(
            intrinsics::StSuperByName(this->GetJSThread(), LoadFromConstantPool(stringId), obj, value, func));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStglobalvar()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "stglobalvar "
                   << "string_id:" << stringId.AsIndex() << ", ";

        uint64_t value = GetAccAsTaggedValue().GetRawData();

        SaveAccToFrame();
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_CHECK(intrinsics::StGlobalVar(this->GetJSThread(), LoadFromConstantPool(stringId), value,
                                                     this->GetBytecodeOffset(), func));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreategeneratorobj()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "creategeneratorobj"
                   << " v" << v0;

        uint64_t genFunc = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateGeneratorObj(this->GetJSThread(), genFunc));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSetgeneratorstate()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto state = this->GetInst().template GetImm<FORMAT, 0>();
        LOG_INST() << "setgeneratorstate"
                   << " v" << v0 << " state" << state;

        uint64_t genFunc = GetRegAsTaggedValue(v0).GetRawData();

        intrinsics::SetGeneratorState(this->GetJSThread(), genFunc, state);
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateasyncgeneratorobj()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "createasyncgeneratorobj"
                   << " v" << v0;

        uint64_t genFunc = GetRegAsTaggedValue(v0).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateAsyncGeneratorObj(this->GetJSThread(), genFunc));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStarrayspread()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "ecmascript::starrayspread"
                   << " v" << v0 << " v" << v1 << "acc";

        uint64_t dst = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t index = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t src = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::StArraySpread(this->GetJSThread(), dst, index, src));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLoadclasscomputedinstancefields()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "loadclasscomputedinstancefields"
                   << " v" << v0;

        uint64_t ctor = GetRegAsTaggedValue(v0).GetRawData();

        SetAccFromTaggedValue(JSTaggedValue(intrinsics::LoadClassComputedInstanceFields(this->GetJSThread(), ctor)));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSetclasscomputedfields()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "setclasscomputedfields"
                   << " class_reg v:" << v0 << " computed_fields v:" << v1;

        uint64_t classReg = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t computedFields = GetRegAsTaggedValue(v1).GetRawData();

        intrinsics::SetClassComputedFields(this->GetJSThread(), classReg, computedFields);
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefineclasswithbuffer()
    {
        auto methodId = this->GetInst().template GetId<FORMAT>().AsIndex();
        auto imm = this->GetInst().template GetImm<FORMAT, 0>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "defineclasswithbuffer"
                   << " method id:" << methodId << " literal id:" << imm << " lexenv: v" << v0 << " parent: v" << v1;

        uint64_t lexenv = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t proto = GetRegAsTaggedValue(v1).GetRawData();
        auto cp = GetConstantPool();
        uint64_t method = cp->GetObjectFromCache(methodId).GetRawData();
        // uint64_t buffer = cp->GetObjectFromCache(imm).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(intrinsics::DefineClassWithBuffer(this->GetJSThread(), method, imm, lexenv, proto,
                                                                      JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaClassfieldadd()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "classfieldadd"
                   << " obj: v" << v0 << " prop: v" << v1;

        uint64_t obj = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t prop = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::ClassFieldAdd(this->GetJSThread(), obj, prop, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDefineclassprivatefields()
    {
        auto literalarrayId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "ldevalbindings"
                   << " literalArrayId:" << literalarrayId.AsIndex();

        auto v0 = this->GetInst().template GetVReg<FORMAT>();
        LOG_INST() << "defineclassprivatefields"
                   << " literalArrayId:" << literalarrayId.AsIndex() << " v0:" << v0;

        uint64_t env = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t ctor = GetAccAsTaggedValue().GetRawData();
        auto cp = GetConstantPool();
        uint64_t privateBuf = cp->GetObjectFromCache(literalarrayId.AsIndex()).GetRawData();
        intrinsics::DefineClassPrivateFields(this->GetJSThread(), privateBuf, env, ctor,
                                             JSTaggedValue(cp).GetRawData());
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaClassprivatemethodoraccessoradd()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "classprivatemethodoraccessoradd"
                   << " ctor: v" << v0 << " obj: v" << v1;

        uint64_t ctor = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetRegAsTaggedValue(v1).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::ClassPrivateMethodOrAccessorAdd(this->GetJSThread(), ctor, obj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaClassprivatefieldadd()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "classprivatefieldadd"
                   << " string id:" << stringId << " ctor: v" << v0 << " obj: v" << v1;

        uint64_t ctor = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::ClassPrivateFieldAdd(this->GetJSThread(), LoadFromConstantPool(stringId), ctor, obj, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaClassprivatefieldget()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "classprivatefieldadd"
                   << " string id:" << stringId << " private contexts: v" << v0 << " obj: v" << v1;

        uint64_t ctor = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetRegAsTaggedValue(v1).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::ClassPrivateFieldGet(this->GetJSThread(), LoadFromConstantPool(stringId), ctor, obj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaClassprivatefieldset()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();
        LOG_INST() << "classprivatefieldset"
                   << " string id:" << stringId << " private contexts: v" << v0 << " obj: v" << v1;

        uint64_t ctor = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetRegAsTaggedValue(v1).GetRawData();
        uint64_t value = GetAccAsTaggedValue().GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::ClassPrivateFieldSet(this->GetJSThread(), LoadFromConstantPool(stringId), ctor, obj, value));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaClassprivatefieldin()
    {
        auto stringId = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "classprivatefieldin"
                   << " string id:" << stringId << " private contexts: v" << v0;

        uint64_t ctor = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetAccAsTaggedValue().GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::ClassPrivateFieldIn(this->GetJSThread(), LoadFromConstantPool(stringId), ctor, obj));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSupercall()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto range = this->GetInst().template GetImm<FORMAT, 0>();
        LOG_INST() << "supercall"
                   << "range: " << range << " v" << v0;

        auto numVregs = this->GetFrame()->GetMethod()->GetNumVregs();

        auto thisFunc = GetAccAsTaggedValue();
        auto newTarget = GetRegAsTaggedValue(numVregs + 1);

        auto thread = JSThread::Cast(this->GetThread());
        auto res = SlowRuntimeStub::SuperCall(thread, thisFunc, newTarget, range, GetStkArgs(v0));
        INTERPRETER_RETURN_IF_ABRUPT(res);
        SetAccFromTaggedValue(res);

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSupercallspread()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        LOG_INST() << "intrinsic::supercallspread"
                   << " array: v" << v0;

        uint64_t array = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t thisFunc = GetAccAsTaggedValue().GetRawData();

        auto numVregs = this->GetFrame()->GetMethod()->GetNumVregs();
        uint64_t newTarget = GetRegAsTaggedValue(numVregs + 1).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::SuperCallSpread(this->GetJSThread(), array, newTarget, thisFunc));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaCreateobjecthavingmethod()
    {
        auto literalarrayId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "createobjecthavingmethod"
                   << " literalArrayId:" << literalarrayId.AsIndex();

        uint64_t env = GetAccAsTaggedValue().GetRawData();
        auto cp = GetConstantPool();
        uint64_t literal = cp->GetObjectFromCache(literalarrayId.AsIndex()).GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::CreateObjectHavingMethod(this->GetJSThread(), literal, env, JSTaggedValue(cp).GetRawData()));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdnan()
    {
        LOG_INST() << "ldnan";

        INTRINSIC_CALL_SETACC(intrinsics::Ldnan());

        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowifsupernotcorrectcall()
    {
        uint16_t imm = this->GetInst().template GetImm<FORMAT, 0>();
        JSTaggedValue thisValue = GetAccAsTaggedValue();
        LOG_INST() << "intrinsic::throwifsupernotcorrectcall"
                   << " imm:" << imm;
        auto thread = JSThread::Cast(this->GetThread());
        JSTaggedValue res = SlowRuntimeStub::ThrowIfSuperNotCorrectCall(thread, imm, thisValue);
        INTERPRETER_RETURN_IF_ABRUPT(res);
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaThrowdeletesuperproperty()
    {
        LOG_INST() << "throwdeletesuperproperty";
        auto thread = JSThread::Cast(this->GetThread());
        SlowRuntimeStub::ThrowDeleteSuperProperty(thread);
        this->MoveToExceptionHandler();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdhomeobject()
    {
        LOG_INST() << "ldhomeobject";
        auto func = GetThisFuncRawValue();
        INTRINSIC_CALL_SETACC(intrinsics::LdHomeObject(this->GetJSThread(), func));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaPoplexenvdyn()
    {
        auto thread = this->GetJSThread();
        auto lexEnv = GetLexicalEnvRawValue();
        auto res = JSTaggedValue(intrinsics::PopLexenvDyn(thread, lexEnv));
        SetLexicalEnv(res);
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaSetobjectwithproto()
    {
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();

        LOG_INST() << "setobjectwithproto"
                   << " v" << v0 << " v" << v1;

        uint64_t proto = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t obj = GetRegAsTaggedValue(v1).GetRawData();

        SaveAccToFrame();
        INTRINSIC_CALL_CHECK(intrinsics::SetObjectWithProto(this->GetJSThread(), proto, obj));
        RestoreAccFromFrame();
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdevalbindings()
    {
        auto literalarrayId = this->GetInst().template GetId<FORMAT>();
        LOG_INST() << "ldevalbindings"
                   << " literalArrayId:" << literalarrayId.AsIndex();
        INTRINSIC_CALL_SETACC(intrinsics::LdEvalBindings(this->GetJSThread(), LoadFromConstantPool(literalarrayId)));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDirecteval()
    {
        auto imm = this->GetInst().template GetImm<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();
        auto v1 = this->GetInst().template GetVReg<FORMAT, 1>();

        LOG_INST() << "directeval"
                   << " status:" << imm << " v0:" << v0 << " v1:" << v1;

        uint64_t arg0 = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t evalBindings = GetRegAsTaggedValue(v1).GetRawData();

        INTRINSIC_CALL_CHECK_SETACC(intrinsics::DirectEval(this->GetJSThread(), imm, arg0, evalBindings));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaLdevalvar()
    {
        auto id = this->GetInst().template GetId<FORMAT>();

        LOG_INST() << "ldevalvar"
                   << " name:" << id.AsIndex();

        uint64_t lexicalContext = GetAccAsTaggedValue().GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::LdEvalVar(this->GetJSThread(), LoadFromConstantPool(id), lexicalContext));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaStevalvar()
    {
        auto id = this->GetInst().template GetId<FORMAT>();
        auto v0 = this->GetInst().template GetVReg<FORMAT, 0>();

        LOG_INST() << "stevalvar"
                   << " name:" << id.AsIndex() << " v0:" << v0;

        uint64_t value = GetRegAsTaggedValue(v0).GetRawData();
        uint64_t lexicalContext = GetAccAsTaggedValue().GetRawData();
        INTRINSIC_CALL_CHECK_SETACC(
            intrinsics::StEvalVar(this->GetJSThread(), LoadFromConstantPool(id), value, lexicalContext));
        this->template MoveToNextInst<FORMAT, true>();
    }

    template <BytecodeInstruction::Format FORMAT>
    ALWAYS_INLINE void HandleEcmaDebugger()
    {
        LOG_INST() << "debugger";
        this->template MoveToNextInst<FORMAT, true>();
    }

    ALWAYS_INLINE JSThread *GetJSThread()
    {
        return JSThread::Cast(this->GetThread());
    }

    void *GetProfileAddress()
    {
        auto method = static_cast<JSMethod *>(this->GetFrame()->GetMethod());
        // Profiling is not initialized
        if (method->GetProfileSize() == 0) {
            return nullptr;
        }
        auto profData = method->GetProfilingVector();
        auto profId = this->GetInst().GetProfileId();
        ASSERT(profId >= 0);
        ASSERT(method->GetProfileSize() > helpers::ToUnsigned(profId));
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto profValue = reinterpret_cast<ObjByIndexOperationProfile::ValueType *>(&profData[profId]);

        return profValue;
    }

    void UpdateTypeOfProfile(coretypes::TaggedType value)
    {
        auto method = static_cast<JSMethod *>(this->GetFrame()->GetMethod());
        // Profiling is not initialized
        if (method->GetProfileSize() == 0) {
            return;
        }
        auto profData = method->GetProfilingVector();
        auto profId = this->GetInst().GetProfileId();
        ASSERT(profId >= 0);
        ASSERT(method->GetProfileSize() > helpers::ToUnsigned(profId));
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto profValue = reinterpret_cast<TypeOfOperationProfile::ValueType *>(&profData[profId]);
        TypeOfOperationProfile::Update(profValue, JSTaggedValue(value));
    }

    void UpdateUnaryArithProfile(coretypes::TaggedType value)
    {
        auto method = static_cast<JSMethod *>(this->GetFrame()->GetMethod());
        // Profiling is not initialized
        if (method->GetProfileSize() == 0) {
            return;
        }
        auto profData = method->GetProfilingVector();
        auto profId = this->GetInst().GetProfileId();
        ASSERT(profId >= 0);
        ASSERT(method->GetProfileSize() > helpers::ToUnsigned(profId));
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto profValue = reinterpret_cast<UnaryOperationProfile::ValueType *>(&profData[profId]);
        UnaryOperationProfile::Update(profValue, JSTaggedValue(value));
    }

    template <bool IS_MOD = false>
    void UpdateBinaryArithProfile(coretypes::TaggedType lhs, coretypes::TaggedType rhs)
    {
        auto left = JSTaggedValue(lhs);
        auto right = JSTaggedValue(rhs);
        auto method = static_cast<JSMethod *>(this->GetFrame()->GetMethod());
        // Profiling is not initialized
        if (method->GetProfileSize() == 0) {
            return;
        }
        auto profData = method->GetProfilingVector();
        auto profId = this->GetInst().GetProfileId();
        ASSERT(profId >= 0);
        ASSERT(method->GetProfileSize() > helpers::ToUnsigned(profId));
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto profValue = reinterpret_cast<BinaryOperationProfile::ValueType *>(&profData[profId]);
        // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon)
        if constexpr (IS_MOD) {
            BinaryOperationProfile::UpdateMod(profValue, left, right);
        } else {
            BinaryOperationProfile::Update(profValue, left, right);
        }
    }

    void UpdateCallProfile(ECMAObject *func)
    {
        auto jsMethod = (JSMethod *)this->GetFrame()->GetMethod();
        if (jsMethod->GetProfileSize() == 0) {
            return;
        }
        auto profId = this->GetInst().GetProfileId();
        ASSERT(profId != -1);
        ASSERT(static_cast<uint32_t>(profId) < jsMethod->GetProfileSize());
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
        auto profile = CallProfile::FromBuffer(jsMethod->GetProfilingVector() + profId);
        ASSERT(profile != nullptr);
        auto *profileTable = this->GetJSThread()->GetEcmaVM()->GetEcmaCallProfileTable();
        profile->Update(func, profileTable);
    }

};  // InstructionHandler

}  // namespace ark::ecmascript

#endif  // PANDA_ECMASCRIPT_INTERPRETER_INL_H
